require File.dirname(__FILE__) + "/red_green_refactoring"

class RedGreenRefactoring

  class TestReporter    
    attr_accessor :passes, :failures, :errors, :silent

    def self.silent
      reporter = self.new()
      reporter.silent = true
      reporter
    end
    
    def initialize
      @tests = @passes = @failures = @errors = 0
      @messages = []
      @silent = false
    end
    
    def test_case test_case
      start = Time.now
      @messages = []
      puts "#{test_case.class.to_s} Started"
      yield # looks like ....F..E... without end of line
      puts ""
      report
      duration =  Time.now - start
      puts "\nFinished in #{duration} seconds."
    end
    
    def test method_name
      @tests += 1
      @method_name = method_name
    end
    
    def pass
      putc "."
      @passes += 1
    end
    
    def fail exception
      putc "F"
      @failures += 1
      log_exception exception
    end
    
    def error exception
      putc "E"
      @errors += 1
      log_exception exception
    end    
    
    def log_exception exception
      @messages << "\n"+@method_name.to_s
      @messages << print_exception(exception)
    end

    def report     
      @messages.push(summary)
      if @failures == 0 && @errors == 0
        @messages.push("\e[32mGREEN\e[0m")
      else
        @messages.push("\e[31mRED\e[0m")
      end
      
      puts @messages.join("\n")
    end
    
    def summary
      "#{@tests} tests, #{@passes} assertions, #{@failures} failures, #{@errors} errors"
    end
    
    def puts(*args)
      super(*args) unless @silent
    end
    
    def putc(*args)
      super(*args) unless @silent
    end

    protected

    def print_exception exception
      #some exception may not contain string in their mesasge...
      message = exception.to_s
      if !message.is_a? String
        message = message.to_s
      end
      message.to_s +
        "\n" +
        remove_rgr_paths(exception.backtrace).join("\n")
    end
    
    def remove_rgr_paths backtrace
      my_path = File.dirname(File.expand_path(__FILE__))
      lines = []
      @all_were_dm_paths = true
      (backtrace.each { |line|
        # gotta split by rb:, split by : would cause trouble on windows (C:\...)
        dir = File.dirname(File.expand_path(line.split('rb:')[0]))
        unless dir == my_path
          lines << line
          @all_were_dm_paths = false
        end
      }).compact
      if @all_were_dm_paths
        return backtrace
      end
      lines
    end
  end

end
  

